package com.czgj.JGB28181.request;

import com.alibaba.fastjson.JSONObject;
import com.czgj.JGB28181.bean.Device;
import com.czgj.JGB28181.bean.DeviceChannel;
import com.czgj.JGB28181.bean.Host;
import com.czgj.JGB28181.bean.PushStreamDevice;
import com.czgj.JGB28181.common.constants.DeviceConstants;
import com.czgj.JGB28181.common.utils.IDUtils;
import com.czgj.JGB28181.common.utils.PortUtils;
import com.czgj.JGB28181.common.utils.RedisUtil;
import com.czgj.JGB28181.media.session.PushStreamDeviceManager;
import com.czgj.JGB28181.message.helper.DigestServerAuthenticationHelper;
import com.czgj.JGB28181.message.helper.SipContentHelper;
import com.czgj.JGB28181.message.session.MessageManager;
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.header.Expires;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.io.ByteArrayInputStream;
import java.text.ParseException;
import java.util.*;

/**
 * SipLayer 服务器
 * <p>
 * SipListener 监听设备的消息
 */
public class SipLayer implements SipListener {

    /**
     * 日志
     */
    private Logger logger = LoggerFactory.getLogger(getClass());

    private SipStackImpl mSipStack;

    private AddressFactory mAddressFactory;

    private HeaderFactory mHeaderFactory;

    private MessageFactory mMessageFactory;

    private SipProvider mTCPSipProvider;
    private SipProvider mUDPSipProvider;

    private long mCseq = 1;
    private long mSN = 1;

    private String mLocalIp;
    private int mLocalPort;
    private String mSipId;
    private String mSipRealm;
    private String mPassword;
    private String mSsrcRealm;
    private String mStreamMediaIp;

    private DigestServerAuthenticationHelper mDigestServerAuthenticationHelper;
    public static final String UDP = "UDP";
    public static final String TCP = "TCP";

    /**
     * 目录响应
     */
    private static final String MESSAGE_CATALOG = "Catalog";
    /**
     * 配置信息
     */
    private static final String MESSAGE_DEVICE_INFO = "DeviceInfo";
    private static final String MESSAGE_BROADCAST = "Broadcast";
    private static final String MESSAGE_DEVICE_STATUS = "DeviceStatus";
    /**
     * 心跳
     */
    private static final String MESSAGE_KEEP_ALIVE = "Keepalive";
    private static final String MESSAGE_MOBILE_POSITION = "MobilePosition";
    private static final String MESSAGE_MOBILE_POSITION_INTERVAL = "Interval";

    // 设备的ID
    private static final String ELEMENT_DEVICE_ID = "DeviceID";

    // 设备列表
    private static final String ELEMENT_DEVICE_LIST = "DeviceList";
    // 名字
    private static final String ELEMENT_NAME = "Name";
    // 状态
    private static final String ELEMENT_STATUS = "Status";

    // 流媒体启动端口
    private static final int STREAM_MEDIA_START_PORT = 10000;
    // 流媒体端口
    private static final int STREAM_MEDIA_END_PORT = 11000;

    // 媒体端口
    private int mStreamPort = STREAM_MEDIA_START_PORT;


    private static final int SSRC_TYPE_PLAY = 0;
    private static final int SSRC_TYPE_HISTORY = 1;
    private static final int SSRC_MIN_VALUE = 0;
    private static final int SSRC_MAX_VALUE = 9999;
    private int mSsrc;

    // 会话 (播放)
    public static final String SESSION_NAME_PLAY = "Play";
    // 会话 (下载)
    public static final String SESSION_NAME_DOWNLOAD = "Download";
    // 会话 (重放)
    public static final String SESSION_NAME_PLAY_BACK = "Playback";


    private MessageManager mMessageManager = MessageManager.getInstance();
    private PushStreamDeviceManager mPushStreamDeviceManager = PushStreamDeviceManager.getInstance();

    public SipLayer(String sipId, String sipRealm, String password, String localIp, int localPort, String streamMediaIp) {
        this.mSipId = sipId;
        this.mLocalIp = localIp;
        this.mLocalPort = localPort;
        this.mSipRealm = sipRealm;
        this.mPassword = password;
        this.mSsrcRealm = mSipId.substring(3, 8);
        this.mStreamMediaIp = streamMediaIp;
    }

    /**
     * 启动服务
     */
    public boolean startServer() {
        return initSip();
    }

    /**
     * 初始化 Sip 服务
     *
     * @return
     */
    @SuppressWarnings("deprecation") //忽略警告
    private boolean initSip() {
        try {
//          1 : 获取到单例对象
            SipFactory sipFactory = SipFactory.getInstance();
//          2 : 设置配置信息
            Properties properties = new Properties();
            properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
            properties.setProperty("javax.sip.IP_ADDRESS", mLocalIp);
            mSipStack = (SipStackImpl) sipFactory.createSipStack(properties);

            mHeaderFactory = sipFactory.createHeaderFactory();
            mAddressFactory = sipFactory.createAddressFactory();
            mMessageFactory = sipFactory.createMessageFactory();
            mDigestServerAuthenticationHelper = new DigestServerAuthenticationHelper();
            //同时监听UDP和TCP
            try {
                ListeningPoint tcpListeningPoint = mSipStack.createListeningPoint(mLocalIp, mLocalPort, "TCP");

                ListeningPoint udpListeningPoint = mSipStack.createListeningPoint(mLocalIp, mLocalPort, "UDP");

                mTCPSipProvider = mSipStack.createSipProvider(tcpListeningPoint);
                mTCPSipProvider.addSipListener(this);

                mUDPSipProvider = mSipStack.createSipProvider(udpListeningPoint);
                mUDPSipProvider.addSipListener(this);
            } catch (Exception e) {
                logger.error("监听 TCP UDP 初始化 initSip 对象出现错误 : ", e);
                return false;
            }
        } catch (Exception e) {
            logger.error("初始化 initSip 对象出现错误 : ", e);
            return false;
        }
        return true;
    }

    /**
     * 终端发送的Request信令
     * (监听摄像头发送过来的请求)
     */
    public void processRequest(RequestEvent evt) {
        Request request = evt.getRequest();
        String method = request.getMethod();
        logger.info("processRequest >>> {}", request);
        try {
//            1 : 登录请求
            if (method.equalsIgnoreCase(Request.REGISTER)) {
                processRegister(evt);
//            2 : 普通消息请求
            } else if (method.equalsIgnoreCase(Request.MESSAGE)) {
                processMessage(evt);
//            3 : 断开请求
            } else if (method.equalsIgnoreCase(Request.BYE)) {
                processBye(evt);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * bye bye的请求
     *
     * @param evt
     * @throws Exception
     */
    private void processBye(RequestEvent evt) throws Exception {
        ServerTransaction serverTransaction = evt.getServerTransaction();
        Dialog dialog = serverTransaction != null ? serverTransaction.getDialog() : null;

        Request request = evt.getRequest();
        CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
        close(mPushStreamDeviceManager.removeByCallId(callIdHeader.getCallId()));

        if (serverTransaction == null || dialog == null) {
            serverTransaction = (isTCP(request) ? mTCPSipProvider : mUDPSipProvider).getNewServerTransaction(request);
        }
        Response response = mMessageFactory.createResponse(Response.OK, request);
        serverTransaction.sendResponse(response);


    }

    /**
     * 普通消息处理
     *
     * @param evt 请求
     * @throws Exception
     */
    private void processMessage(RequestEvent evt) throws Exception {
//      1 : 获取到请求对象
        Request request = evt.getRequest();
        SAXReader reader = new SAXReader();
        //reader.setEncoding("GB2312");
        Document xml = reader.read(new ByteArrayInputStream(request.getRawContent()));
        Element rootElement = xml.getRootElement();
//      2 : 获取到消息类型
        String cmd = rootElement.element("CmdType").getStringValue();
//      3 : 获取到设备的ID
        Element deviceIdElement = rootElement.element(ELEMENT_DEVICE_ID);
        if (deviceIdElement == null) {
            return;
        }
//        设备的ID
        String deviceId = deviceIdElement.getText().toString();
        Response response = null;

        /**
         心跳，
         */
        //如果redis中设备在线，更新。
        //不在线回复 400
        if (MESSAGE_KEEP_ALIVE.equals(cmd)) {
//            查看当前设备的ID ,是否在线
            if (RedisUtil.checkExist(deviceId)) {
//                更新在线时间
                RedisUtil.expire(deviceId, RedisUtil.EXPIRE);
            } else {
//                发送400请求 , 表示设备没注册上来
                response = mMessageFactory.createResponse(Response.BAD_REQUEST, request);
            }
        }

        //目录响应，保存到redis (日志) (通道)
        else if (MESSAGE_CATALOG.equals(cmd)) {
//            获取到通道列表
            Element deviceListElement = rootElement.element(ELEMENT_DEVICE_LIST);
            if (deviceListElement == null) {
                return;
            }
            Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
            if (deviceListIterator != null) {
                String deviceStr = RedisUtil.get(deviceId);
                if (StringUtils.isEmpty(deviceStr)) {
                    return;
                }
                Device device = JSONObject.parseObject(deviceStr, Device.class);
//                获取到设备的通道
                Map<String, DeviceChannel> channelMap = device.getChannelMap();
                if (channelMap == null) {
                    channelMap = new HashMap<String, DeviceChannel>(5);
                    device.setChannelMap(channelMap);
                }
                //遍历DeviceList
                while (deviceListIterator.hasNext()) {
                    Element itemDevice = deviceListIterator.next();

//                    拿到设备的ID
                    Element channelDeviceElement = itemDevice.element(ELEMENT_DEVICE_ID);

                    if (channelDeviceElement == null) {
                        continue;
                    }
//                    拿到通道的ID
                    String channelDeviceId = channelDeviceElement.getText().toString();
                    Element channdelNameElement = itemDevice.element(ELEMENT_NAME);
//                    通道名字
                    String channelName = channdelNameElement != null ? channdelNameElement.getText().toString() : "";
                    Element statusElement = itemDevice.element(ELEMENT_STATUS);
                    String status = statusElement != null ? statusElement.getText().toString() : "ON";
//                   如果通道存在,则不更新 , 或者更新
                    DeviceChannel deviceChannel = channelMap.containsKey(channelDeviceId) ? channelMap.get(channelDeviceId) : new DeviceChannel();
                    deviceChannel.setName(channelName); // 通道名字
                    deviceChannel.setDeviceId(channelDeviceId); //通道高ID
//                    在线或者离线
                    deviceChannel.setStatus(status.equals("ON") ? DeviceConstants.ON_LINE : DeviceConstants.OFF_LINE);
//                    添加通道
                    channelMap.put(channelDeviceId, deviceChannel);
                }
                //    更新Redis
                RedisUtil.set(deviceId, JSONObject.toJSONString(device));
            }
        }
        if (response == null) {
//            回复ok
            response = mMessageFactory.createResponse(Response.OK, request);
        }
//        发送请求
        sendResponse(response, getServerTransaction(evt));

    }

    private ServerTransaction getServerTransaction(RequestEvent evt) throws Exception {
        ServerTransaction serverTransaction = evt.getServerTransaction();
        if (serverTransaction == null) {
            Request request = evt.getRequest();
            serverTransaction = (isTCP(request) ? mTCPSipProvider : mUDPSipProvider).getNewServerTransaction(request);
        }
        return serverTransaction;

    }

    /**
     * 登录请求处理
     *
     * @param evt 请求对象
     * @throws Exception 异常
     */
    private void processRegister(RequestEvent evt) throws Exception {
//      1 : 获取到请求对象
        Request request = evt.getRequest();
        ServerTransaction serverTransaction = evt.getServerTransaction();
//      2 : 判断当前请求是TCP还是UDP
        boolean isTcp = isTCP(request);
        if (serverTransaction == null) {
            serverTransaction = (isTCP(request) ? mTCPSipProvider : mUDPSipProvider).getNewServerTransaction(request);
        }
        Response response = null;
        boolean passwordCorrect = false;

        // 表示是不是注册的请求
        boolean isRegisterSuceess = false;
//        此次注册请求的连接对象
        Device device = null;
//      3 : 获取到头信息
        Header header = request.getHeader(AuthorizationHeader.NAME);
        //携带授权头
        //校验密码是否正确
        if (header != null) {
            passwordCorrect = mDigestServerAuthenticationHelper.doAuthenticatePlainTextPassword(request, mPassword);
            if (!passwordCorrect) {
                logger.info("密码错误");
            }
        }

        //未携带授权头或者密码错误 回复401
        if (header == null || !passwordCorrect) {
            response = mMessageFactory.createResponse(Response.UNAUTHORIZED, request);
            mDigestServerAuthenticationHelper.generateChallenge(mHeaderFactory, response, mSipRealm);
        }
        //携带授权头并且密码正确
        else if (header != null && passwordCorrect) {
            response = mMessageFactory.createResponse(Response.OK, request);
            //添加date头
            response.addHeader(mHeaderFactory.createDateHeader(Calendar.getInstance(Locale.ENGLISH)));
            ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME);
            //添加Contact头
            response.addHeader(request.getHeader(ContactHeader.NAME));
            //添加Expires头
            response.addHeader(request.getExpires());
            //注销成功
            if (expiresHeader != null && expiresHeader.getExpires() == 0) {

            }
            //注册成功
            else {
                isRegisterSuceess = true;
                //1.获取到通信地址等信息，保存到Redis
                FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
                ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
//              获取到host信息
                Host host = getHost(viaHeader);
//              获取到设备的ID信息 34020000001320000001
                String deviceId = getDeviceId(fromHeader);
                device = new Device();
                device.setDeviceId(deviceId);
                device.setHost(host);
                device.setProtocol(isTcp ? TCP : UDP);
            }
        }
//       向摄像头返回成功的响应
        sendResponse(response, serverTransaction);
        //注册成功
        //1.保存到redis
        //2.下发catelog查询目录
        if (isRegisterSuceess && device != null) {
            String callId = IDUtils.id();
            String fromTag = IDUtils.id();
//          把注册请求 , 存放到缓存中 , key == 设备的userId
            RedisUtil.set(device.getDeviceId(), RedisUtil.EXPIRE, JSONObject.toJSONString(device));
//          1 ： 向对应设备,发送获取日志的请求
            sendCatalog(device, callId, fromTag, mCseq, String.valueOf(mSN));
        }
    }

    /**
     * 发送获取日志列表的请求
     *
     * @param device  设备通信信息
     * @param callId  id
     * @param fromTag 来自Tag
     * @param cseq
     * @param sn
     * @throws Exception
     */
    private void sendCatalog(Device device, String callId, String fromTag, long cseq, String sn) throws Exception {
//        通信信息
        Host host = device.getHost();
//        设备的ID
        String deviceId = device.getDeviceId();
//        创建请求对象
        Request request = createRequest(deviceId, host.getAddress(), host.getWanIp(), host.getWanPort(), device.getProtocol(),
                mSipId, mSipRealm, fromTag,
                deviceId, mSipRealm, null,
                callId, cseq, Request.MESSAGE);

        String catalogContent = SipContentHelper.generateCatalogContent(deviceId, sn);
        ContentTypeHeader contentTypeHeader = mHeaderFactory.createContentTypeHeader("Application", "MANSCDP+xml");
        request.setContent(catalogContent, contentTypeHeader);
        request.addHeader(contentTypeHeader);
//        发送请求
        sendRequest(request);

    }

    /**
     * 发送推流请求
     *
     * @param device      设备的ID用户ID
     * @param sessionName 会话名称
     * @param callId      连接ID
     * @param channelId   通道ID
     * @param port        端口
     * @param ssrc        ssrc
     * @param isTcp       是否是TCP
     * @throws Exception 异常
     */
    public void sendInvite(Device device, String sessionName, String callId, String channelId, int port, String ssrc,
                           boolean isTcp) throws Exception {

        String fromTag = IDUtils.id();
        Host host = device.getHost();
        String realm = channelId.substring(0, 8);
        Request request = createRequest(channelId, host.getAddress(), host.getWanIp(), host.getWanPort(), device.getProtocol(),
                mSipId, mSipRealm, fromTag,
                channelId, realm, null,
                callId, 20, Request.INVITE);
        //添加Concat头
        Address concatAddress = mAddressFactory.createAddress(mAddressFactory.createSipURI(mSipId, mLocalIp.concat(":").concat(String.valueOf(mLocalPort))));
        request.addHeader(mHeaderFactory.createContactHeader(concatAddress));
        //添加消息体
        String content = SipContentHelper.generateRealTimeMeidaStreamInviteContent(mSipId, mStreamMediaIp, port, isTcp, false, sessionName, ssrc);
        ContentTypeHeader contentTypeHeader = mHeaderFactory.createContentTypeHeader("Application", "SDP");
        request.setContent(content, contentTypeHeader);
        //request.addHeader(contentTypeHeader);
        sendRequest(request);
    }

    private Request createRequest(String deviceId, String address, String targetIp, int targetPort, String protocol,
                                  String fromUserInfo, String fromHostPort, String fromTag,
                                  String toUserInfo, String toHostPort, String toTag,
                                  String callId,
                                  long cseqNo, String method) throws ParseException, InvalidArgumentException {
        //请求行
        SipURI requestLine = mAddressFactory.createSipURI(deviceId, address);
        //Via头
        ArrayList viaHeaderList = new ArrayList();
        ViaHeader viaHeader = mHeaderFactory.createViaHeader(targetIp, targetPort, protocol, null);
        viaHeader.setRPort();
        viaHeaderList.add(viaHeader);

        //To头
        SipURI toAddress = mAddressFactory.createSipURI(toUserInfo, toHostPort);
        Address toNameAddress = mAddressFactory.createAddress(toAddress);
        ToHeader toHeader = mHeaderFactory.createToHeader(toNameAddress, toTag);

        //From头
        SipURI from = mAddressFactory.createSipURI(fromUserInfo, fromHostPort);
        Address fromNameAddress = mAddressFactory.createAddress(from);
        FromHeader fromHeader = mHeaderFactory.createFromHeader(fromNameAddress, fromTag);

        //callId
        CallIdHeader callIdHeader = protocol.equals(TCP) ? mTCPSipProvider.getNewCallId() : mUDPSipProvider.getNewCallId();
        ;
        callIdHeader.setCallId(callId);

        //Cseq
        CSeqHeader cSeqHeader = mHeaderFactory.createCSeqHeader(cseqNo, method);

        //Max_forward
        MaxForwardsHeader maxForwardsHeader = mHeaderFactory.createMaxForwardsHeader(70);

        return mMessageFactory.createRequest(requestLine, method, callIdHeader, cSeqHeader, fromHeader, toHeader,
                viaHeaderList, maxForwardsHeader);

    }

    private boolean isTCP(Request request) {
        return isTCP((ViaHeader) request.getHeader(ViaHeader.NAME));
    }

    private boolean isTCP(Response response) {
        return isTCP((ViaHeader) response.getHeader(ViaHeader.NAME));
    }

    private boolean isTCP(ViaHeader viaHeader) {
        String protocol = viaHeader.getProtocol();
        return protocol.equals("TCP");
    }

    private String getDeviceId(FromHeader fromHeader) {
        AddressImpl address = (AddressImpl) fromHeader.getAddress();
        SipUri uri = (SipUri) address.getURI();
        String user = uri.getUser();
        return user;
    }

    /**
     * 获取到请求的host信息
     *
     * @param viaHeader 请求头
     */
    private Host getHost(ViaHeader viaHeader) {
        String received = viaHeader.getReceived();
        int rPort = viaHeader.getRPort();
        //本地模拟设备 received 为空 rPort 为 -1
        //解析本地地址替代
        if (StringUtils.isEmpty(received) || rPort == -1) {
            received = viaHeader.getHost();
            rPort = viaHeader.getPort();
        }
        Host host = new Host();
//        通信的ip
        host.setWanIp(received);
//        通信的端口
        host.setWanPort(rPort);
//        设置地址
        host.setAddress(received.concat(":").concat(String.valueOf(rPort)));
        return host;
    }

    private void sendResponse(Response response, ServerTransaction serverTransaction) throws Exception {
        logger.info("sendResponse >>> {}", response);
        serverTransaction.sendResponse(response);
    }

    /**
     * 发送请求
     *
     * @param request 请求
     */
    private void sendRequest(Request request) throws SipException {
        logger.info("sendRequest >>> {}", request);
        ClientTransaction clientTransaction = (isTCP(request) ? mTCPSipProvider : mUDPSipProvider).getNewClientTransaction(request);
        clientTransaction.sendRequest();
    }

    /**
     * 终端发送的Response信令
     * 服务器下发给终端的Request得到响应
     */
    public void processResponse(ResponseEvent evt) {
        Response response = evt.getResponse();
        logger.info("processResponse >>> {}", response);
        CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
        String method = cseqHeader.getMethod();
        try {
            //实时流请求响应
            if (Request.INVITE.equals(method)) {
                int statusCode = response.getStatusCode();
                //trying不会回复
                if (statusCode == Response.TRYING) {

                }
                //成功响应
                //下发ack
                if (statusCode == Response.OK) {
                    ClientTransaction clientTransaction = evt.getClientTransaction();
                    if (clientTransaction == null) {
                        logger.error("回复ACK时，clientTransaction为null >>> {}", response);
                        return;
                    }
                    Dialog clientDialog = clientTransaction.getDialog();

                    CSeqHeader clientCSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
                    long cseqId = clientCSeqHeader.getSeqNumber();
					/*
					createAck函数，创建的ackRequest，会采用Invite响应的200OK，中的contact字段中的地址，作为目标地址。
					有的终端传上来的可能还是内网地址，会造成ack发送不出去。接受不到音视频流
					所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。
					 */
                    Request ackRequest = clientDialog.createAck(cseqId);
                    SipURI requestURI = (SipURI) ackRequest.getRequestURI();
                    ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
                    requestURI.setHost(viaHeader.getHost());
                    requestURI.setPort(viaHeader.getPort());
                    clientDialog.sendAck(ackRequest);
                    CallIdHeader callIdHeader = (CallIdHeader) ackRequest.getHeader(CallIdHeader.NAME);
                    //写入消息管理器
                    mMessageManager.put(callIdHeader.getCallId(), clientDialog);
                    logger.info("sendAck >>> {}", ackRequest);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.toString());
        }
    }

    /**
     * 停止推流，删除session，断开通道
     *
     * @throws SipException
     */
    private void close(PushStreamDevice pushStreamDevice) throws SipException {
        if (pushStreamDevice != null) {
            pushStreamDevice.getServer().stopServer();
            pushStreamDevice.getObserver().stopRemux();
        }
    }

    public void sendBye(String callId) throws SipException {
        PushStreamDevice pushStreamDevice = mPushStreamDeviceManager.removeByCallId(callId);
        if (pushStreamDevice != null) {
            close(pushStreamDevice);
            Dialog dialog = pushStreamDevice.getDialog();
            if (dialog != null) {
                Request byeRequest = dialog.createRequest(Request.BYE);
                ClientTransaction clientTransaction = (isTCP(byeRequest) ? mTCPSipProvider : mUDPSipProvider).getNewClientTransaction(byeRequest);
                dialog.sendRequest(clientTransaction);
                logger.info("sendRequest >>> {}", byeRequest);
            }
        }

    }

    public String getSsrc(boolean isRealTime) {
        StringBuffer buffer = new StringBuffer(15);
        buffer.append(String.valueOf(isRealTime ? 0 : 1));
        buffer.append(mSsrcRealm);
        if (mSsrc >= SSRC_MAX_VALUE) {
            mSsrc = SSRC_MIN_VALUE;
        }
        String ssrcStr = String.valueOf(mSsrc);
        int length = ssrcStr.length();
        for (int i = length; i < 4; i++) {
            buffer.append("0");
        }
        buffer.append(String.valueOf(ssrcStr));

        return buffer.toString();
    }

    /**
     * 获取到端口
     *
     * @param isTcp 是否是TCP
     * @return 返回端口
     */
    public int getPort(boolean isTcp) {
        int resultPort = 0;
        if (PortUtils.isUsing(isTcp, mStreamPort)) {
            resultPort = PortUtils.findAvailablePortRange(STREAM_MEDIA_START_PORT, STREAM_MEDIA_END_PORT, isTcp);
        }
        resultPort = mStreamPort;
        mStreamPort++;
        if (mStreamPort > STREAM_MEDIA_END_PORT) {
            mStreamPort = STREAM_MEDIA_START_PORT;
        }
        return resultPort;
    }

    /**
     * 会话结束
     */
    public void processDialogTerminated(DialogTerminatedEvent evt) {

    }

    /**
     * UDPSocket通道异常
     */
    public void processIOException(IOExceptionEvent evt) {

    }

    /**
     * 超时
     * 下发的Request未能得到响应
     */
    public void processTimeout(TimeoutEvent evt) {

    }

    /**
     * 事务结束
     */
    public void processTransactionTerminated(TransactionTerminatedEvent evt) {

    }

}
